package ao.ai.ml.algo.supervised.classification.linear.discriminative;

import ao.ai.ml.algo.supervised.classification.model.learner.ext.BinaryLearner;
import ao.ai.ml.algo.supervised.model.example.Example;
import ao.ai.ml.algo.supervised.model.hypothesis.ext.BinaryClassificationHypothesis;
import ao.ai.ml.model.feature_set.ext.cat.bin.SingleBinaryFeature;
import ao.ai.ml.model.feature_set.ext.num.NumericalFeatureList;
import ao.ai.ml.model.feature_set.impl.BinaryScalar;
import ao.util.math.rand.Rand;

import java.util.List;

/**
 * User: aostrovsky
 * Date: 5-Feb-2010
 * Time: 10:53:12 PM
 */
public class MeanBinaryClassifier
        implements BinaryLearner
{
    //-------------------------------------------------------------------------
    @Override
    public BinaryClassificationHypothesis learn(
            List<? extends Example<
                    ? extends NumericalFeatureList,
                    ? extends SingleBinaryFeature>>
                data)
    {
        if (data.isEmpty())
        {
            return null;
        }

        final Example<? extends NumericalFeatureList,
                      ? extends SingleBinaryFeature>
                arbitraryExample = data.get(0);

        int nTrue = 0;
        for (Example<? extends NumericalFeatureList,
                     ? extends SingleBinaryFeature>
                datum : data)
        {
            boolean val = datum.output().binaryCategory();
            if (val)
            {
                nTrue++;
            }
        }

        final double trueProb = (double) nTrue / data.size();
        return new BinaryClassificationHypothesis() {
            @Override public double probabilityOfPositive(
                    NumericalFeatureList input) {
                return trueProb;
            }

            @Override public double probabilityOf(
                    NumericalFeatureList input, int categoryIndex) {
                return probabilityOfPositive(input);
            }

            @Override public SingleBinaryFeature predict(
                    NumericalFeatureList input) {
                return new BinaryScalar(
                        Rand.nextBoolean( trueProb ),
                        arbitraryExample.output().type());
            }

            @Override public String toString() {
                return trueProb + " positive";
            }
        };
    }


    //-------------------------------------------------------------------------
    @Override
    public String toString()
    {
        return "Mean Binary Classifier";
    }
}
